#ifndef _U_CLIENT_SERVER_H_
#define _U_CLIENT_SERVER_H_

#include <QObject>
#include <QIODevice>
#include <QSettings>
#include <json/json.h>
#include <iostream>

enum class OPERATOR
{
	SAMEINFO,       //服务器返回相同信息 
    JSONINFO,       //服务器返回default.json文件内容
    UPDATEINFO,
    ADDBOOK,        //添加书籍信息到数据库
    QUERYBOOK,      //查询书籍
    DELETEBOOK,     //删除书籍        (暂时是单个删除)
    REVISEBOOK,     //修改书籍信息     (暂时是单个修改)
	UNKNINFO
};

class QUdpSocket;
class UClientServer  : public QObject
{
	Q_OBJECT
public:signals:
	void alreadyRead(const OPERATOR type, QByteArray datagram);

public:
	static UClientServer* Instance();
	~UClientServer();
	void sendMessage(const QString& text);
	void getDefaultJson();
    void updateJson(const QByteArray& data);
    void addBook(const QString& title, const QString& author, const QString& press, const QString& isbn, const QString& date, const QString& image);
    void reviseBook(const QString& title, const QString& author, const QString& press, const QString& isbn, const QString& date, const QString& initisbn);
    void queryBook(const QString& title, const QString& isbn, const QString& author);
    void deleteBook(const QString& isbn);
    void readConfig();

    QString serverAddress;
    quint16 serverPort;

private:
	UClientServer(QObject* parent = nullptr);
	UClientServer(const UClientServer&) = delete;
	UClientServer(UClientServer&&) = delete;
    OPERATOR getOperatorType(const QByteArray& Type);
	void readResponse();

	QUdpSocket* m_pSocket;


    template<typename T>// 基础模板，用于递归终止  
    void writeToByteArray(QDataStream& dataStream, T&& arg)
    {
        dataStream << std::forward<T>(arg);
    }
    template<typename T, typename... Args>// 递归模板，用于处理多个参数  
    void writeToByteArray(QDataStream& dataStream, T&& first, Args&&... args)
    {
        dataStream << std::forward<T>(first);
        if (sizeof...(args) > 0)writeToByteArray(dataStream, std::forward<Args>(args)...);
    }
    template<typename... Args>// 封装函数，便于调用  
    QByteArray serialize(Args&&... args)
    {
        QByteArray byteArray;
        QDataStream dataStreamData(&byteArray, QIODevice::WriteOnly);
        writeToByteArray(dataStreamData, std::forward<Args>(args)...);
        return byteArray;
    }
};
#endif